package cn.iocoder.yudao.server.framework.filter;

import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.web.config.WebProperties;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;

/**
 * @author lxc
 * @description:
 * @date 2023/12/12 15:22
 */
@Slf4j
public class CheckParamFilter extends OncePerRequestFilter {
    protected final WebProperties webProperties;

    public CheckParamFilter(WebProperties webProperties) {
        this.webProperties = webProperties;
    }

    private static final List<String> URL_PATTERNS = Arrays.asList(
            //学生端
            "/app-api/student/web-student/update",
            "/app-api/student/invite/update",
            "app-api/student/student-curriculum-vitae/create",
            "app-api/student/student-curriculum-vitae/update",
            "/app-api/student/web-student/changeStudentPhone",
            "/app-api/student/message/replyMessage",
            "/app-api/student/message/sendMessage",
            "/app-api/student/message/changeMessageStatus",
            "/app-api/student/message/allchangeMessageStatus",
            "/app-api/student/collect-job/createOrUpdateCollectJob",
            "/app-api/student/collect-company/createOrUpdateCollectCompany",
            "/app-api/student/entry/create",
            "/app-api/student/entry/uploadAnnex",
            "/app-api/student/entry/update",
            "/app-api/student/student-curriculum-vitae/update",
            "/app-api/student/feedback/update",
            "/admin-api/enterprise/enterprise-job/updateBatchRecoveryEnterpriseJob",
            "/admin-api/enterprise/company/update",
            "/admin-api/enterprise/enterprise-job/updateJobDate",
            "/admin-api/enterprise/enterprise-job/setJobTopStatus",
            "/admin-api/enterprise/enterprise-job/setJobStatus",
            "/admin-api/enterprise/curriculum-vitae-send-record/saveEnterpriseCollect",
            "/admin-api/enterprise/curriculum-vitae-send-record/saveEnterpriseNotes",
            "/admin-api/enterprise/interview-invite/createList",
            "/admin-api/enterprise/interview-invite/update",
            "/admin-api/enterprise/interview-invite/inSend",
            "/admin-api/member/job/updateJobFixed",
            "/admin-api/enterprise/enterprise-job/updateEnterpriseJobFixed",
            "/admin-api/infra/config/updateDayFlowInfo",
            "/admin-api/system/push-manage/update",
            "/admin-api/system/push-manage/create",
            "/admin-api/member/company/updateOrderNum",
            "/admin-api/enterprise/company/askAuthentication",
            "/admin-api/enterprise/company/user-update",
            "/admin-api/enterprise/company/updatePhone",
            "/admin-api/enterprise/company/user-create",
            "/admin-api/enterprise/company/user-update",
            "/admin-api/enterprise/company/user-son-update",
            "/admin-api/enterprise/company/isRealName",
            "/admin-api/enterprise/company/updateCompanyUserInfo",
            "/admin-api/member/student/saveStudent",
            "/admin-api/member/newsStudyInfo/updateBatch",
            "/admin-api/member/newsStudyInfo/create",
            "/admin-api/member/newsStudyType/create",
            "/admin-api/member/newsStudyInfo/update",
            "/admin-api/member/newsStudyType/update",
            "/admin-api/member/banner/create",
            "/admin-api/member/banner/update",
            "/admin-api/member/company/create",
            "/admin-api/member/company/update",
            "/admin-api/member/curriculum-vitae-send-record/create",
            "/admin-api/member/curriculum-vitae-send-record/update",
            "/admin-api/member/interview-invite/create",
            "/admin-api/member/interview-invite/update",
            "/admin-api/member/job/admin/createJob",
            "/admin-api/member/job/admin/editJob",
            "/admin-api/member/student/create",
            "/admin-api/member/student/update",
            "/admin-api/member/student-curriculum-vitae/create",
            "/admin-api/member/student-curriculum-vitae/update",
            "/admin-api/member/student-show/create",
            "/admin-api/member/student-show/update",
            "/admin-api/system/user-change-mobile-recordrecord/authenticationUserPhone",
            "/admin-api/member/collect-notes/saveCollect",
            "/admin-api/member/collect-notes/saveNotes",
            "/admin-api/member/job/admin/examinJob",
            "/admin-api/member/job/admin/updateJobDate",
            "/admin-api/member/job/create",
            "/admin-api/member/curriculum-vitae-send-record/sendStudentCurriculumVitae",
            "/admin-api/member/operate/user-create",
            "/admin-api/member/operate/user-update",
            "/admin-api/member/student-curriculum-vitae/update",
            "/admin-api/member/student-curriculum-vitae/create",
            "/admin-api/member/company/company/authentication",
            "/admin-api/recruitCompany/updateRankingStatus"
            );


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws IOException, ServletException {
        String requestURI = request.getRequestURI();
        Boolean checkedSwitch = webProperties.getAdminUi().getCheckedSwitch();
        if (checkedSwitch && URL_PATTERNS.contains(requestURI)) {
            log.info("开始校验参数敏感词,requestURI:" + requestURI + ",method:" + request.getMethod());
            try {
                String parameters = getParameters(request);
                if (StringUtils.isNotBlank(parameters)) {
                    Boolean aBoolean = SolutionUtils.checkParams(parameters, requestURI);
                    log.info("开始校验参数敏感词返回结果,requestURI:" + requestURI + ",aBoolean:" + aBoolean);
                    if (!aBoolean) {
                        ErrorCode errorCode = new ErrorCode(-101, "提交数据不合规,请仔细检测");
                        out(response, errorCode);
                        WebFrameworkUtils.setCommonResult(request,CommonResult.error(errorCode));
                        return;
                    }
                }
            } catch (IOException e) {
                log.error("检测提交数据异常", e);
                ErrorCode errorCode = new ErrorCode(-102, "检测提交数据异常");
                out(response, errorCode);
                WebFrameworkUtils.setCommonResult(request,CommonResult.error(errorCode));
                return;
            }
        }
        filterChain.doFilter(request, response);
    }

    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) {
        // 只处理 json 请求内容
        boolean a = StrUtil.startWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE);
        //只处理admin-api，app-api开头的
        boolean b = (StrUtil.startWithAny(request.getRequestURI(), webProperties.getAdminApi().getPrefix(),
                webProperties.getAppApi().getPrefix()));
        return !(a && b);
    }

    public static void out(ServletResponse response, ErrorCode r) {
        PrintWriter writer = null;
        try {
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            httpResponse.setCharacterEncoding("utf-8");
            httpResponse.setHeader("Content-Type", "text/html; charset=utf-8");
            httpResponse.setContentType("application/json; charset=utf-8");
            writer = httpResponse.getWriter();
            String result = JSON.toJSONString(r, SerializerFeature.WriteNullStringAsEmpty);
            writer.write(result.toCharArray());
        } catch (Exception e) {
            log.error("输出JSON异常,可以忽略", e);
        } finally {
            if (null != writer) {
                writer.flush();
                writer.close();
            }
        }
        return;
    }


    //获取参数
    public static String getParameters(HttpServletRequest request) throws IOException {
        BufferedReader streamReader = new BufferedReader(new InputStreamReader(request.getInputStream(), "UTF-8"));
        StringBuilder responseStrBuilder = new StringBuilder();
        String inputStr;
        while ((inputStr = streamReader.readLine()) != null) {
            responseStrBuilder.append(inputStr);
        }
        return responseStrBuilder.toString();
    }
}
